package kulstats;

import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;

public class StatisticsManager {
	//private DAO dao;
	private static final DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
	private static final ActivityManager activityManager = Registry.activityManager();
	private static final UserManager userManager = Registry.userManager();
	private static final QuestionnaireManager questionnaireManager = Registry.questionnaireManager();
	private static final CourseManager courseManager = Registry.courseManager();
	User currentUser;
	
	public StatisticsManager() { //DAO dao) {
		//this.dao = dao;
	}
	
	private List<Entity> convertUserList(List<String> UserIDs, boolean all)
	{
		List<Entity> list = new ArrayList<Entity>();
		if (!all){
			for (int i = 0; i < UserIDs.size(); i++){
				list.add(userManager.getUserEntity(UserIDs.get(i)).get(0));
			}	
		}
		else{
			list = userManager.getAllUsers();
		}
		
		return list;
	}
	
	private String getStatType(Activity act, String charttype){
		String retstr = "";
		if (charttype.equals("types")){
				retstr = act.getAType().toString();
		}
		else if (charttype.equals("courses")){
			Course crs = null;
			if (act instanceof getCourseable){
				crs = ((getCourseable)act).getCourse();
				retstr = crs.getName();
			}
		}
		else if (charttype.equals("spare_time")){
			if (act instanceof SpareTime){
				retstr = ((SpareTime)act).getSpareTimeType().toString();
			}
		}
		return retstr;
	}

	// TODO: deze methodes doen +1 voor de maand, omdat we date gebruiken, dit kan mogelijks tot rare dingen leiden (?)
	private List<String> createDateStringKeys(Date Start, Date Stop, StatisticsDateType statType)
	{
		List<String> data = new LinkedList<String>();
		GregorianCalendar stopcal = new GregorianCalendar();
		stopcal.setTime(Stop);
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(Start);
		switch (statType)
		{
			case DAILY:
				while (cal.before(stopcal)){
					data.add(""+cal.get(GregorianCalendar.DAY_OF_MONTH)+"/"+(cal.get(GregorianCalendar.MONTH)+1));
					cal.add(GregorianCalendar.DAY_OF_MONTH, 1);
				}
				break;
			case WEEKLY:
				while (cal.before(stopcal)){
					data.add(""+cal.get(GregorianCalendar.WEEK_OF_YEAR));
					cal.add(GregorianCalendar.WEEK_OF_YEAR, 1);
				}
				break;
			case MONTHLY:
				while (cal.before(stopcal)){
					data.add(""+(cal.get(GregorianCalendar.MONTH)+1));
					cal.add(GregorianCalendar.MONTH, 1);
				}
				break;
		}		
		return data;
	}
	
	private String getDateStatType(Date date, StatisticsDateType statType)
	{
		String ret = "";
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(date);
		switch (statType)
		{
			case DAILY:
				ret = ""+cal.get(GregorianCalendar.DAY_OF_MONTH) + "/" + (cal.get(GregorianCalendar.MONTH)+1);
				break;
			case WEEKLY:
				ret = ""+cal.get(GregorianCalendar.WEEK_OF_YEAR);
				break;
			case MONTHLY:
				ret = ""+(cal.get(GregorianCalendar.MONTH)+1);
				break;
		}
		
		return ret;
	}

	/*
	 * String -> bezigheid
	 * Long -> gespendeerde tijd
	 */
	public Map<String, Long> statTimeSpend(List<String> UserIDs, boolean all, String charttype, Date Start, Date Stop)
	{
		currentUser = userManager.getCurrentUser();
		Map<String, Long> data = new HashMap<String, Long>();
		List<Entity> userlist = convertUserList(UserIDs, all);
		for (int i = 0; i < userlist.size(); i++){
			Entity user = userlist.get(i);
			List<Activity> activities = activityManager.getActivitiesFiltered(user.getKey(), Start, Stop);
			for (int j = 0; j < activities.size(); j++){
				Activity act = activities.get(j);
				String datatype = "";
				datatype = getStatType(act, charttype);
				
				// course must be in currentuser's course list
				boolean courseisinuserscourselist = false;
				if (act instanceof getCourseable){
					Course crs = ((getCourseable)act).getCourse();
					if (currentUser.getAllCourseIDs().contains(crs.getCourseID())){
						courseisinuserscourselist = true;
					}
				}
				else{
					courseisinuserscourselist = true;
				}
				
				if (datatype != ""
						&& courseisinuserscourselist){
					long timespent = 0;
					if (act.getStopDate() != null && act.getStartDate() != null){
						timespent = act.getStopDate().getTime() - act.getStartDate().getTime();
						if (act instanceof Study){
							timespent -= ((Study)act).getPaused()*60*1000;
						}
					}
					if (data.containsKey(datatype)){
						data.put(datatype, data.get(datatype)+timespent);
					}else{
						data.put(datatype, timespent);
					}
				}
			}
		}
		return data;
	}
	
	public Map<String, LinkedHashMap<String, Long>> statTimeSpentBar(List<String> UserIDs, boolean all, String charttype, StatisticsDateType statdtype, Date Start, Date Stop)
	{
		List<String> l = createDateStringKeys(Start, Stop, statdtype);
		Map<String, LinkedHashMap<String, Long>> data = new LinkedHashMap<String, LinkedHashMap<String, Long>>();
		for (int i = 0; i < l.size(); i++){
			data.put(l.get(i), new LinkedHashMap<String, Long>());
		}
		List<Entity> userlist = convertUserList(UserIDs, all);
		for (int i = 0; i < userlist.size(); i++){
			Entity user = userlist.get(i);
			List<Activity> activities = activityManager.getActivitiesFiltered(user.getKey(), Start, Stop);
			for (int j = 0; j < activities.size(); j++){
				Activity act = activities.get(j);
				String datatype = getStatType(act, charttype);
				String datadatetype = getDateStatType(act.getStartDate(), statdtype);
				
				if (data.containsKey(datadatetype)){
					LinkedHashMap<String, Long> lhm = data.get(datadatetype);
					if (datatype != ""){
						long timespent = 0;
						if (act.getStopDate() != null && act.getStartDate() != null){
							timespent = act.getStopDate().getTime() - act.getStartDate().getTime();
						}
						if (lhm.containsKey(datatype)){
							lhm.put(datatype, lhm.get(datatype)+timespent);
						}else{
							lhm.put(datatype, timespent);
						}
						
						data.put(datadatetype, lhm);
					}
				}
				
				
			}
		}
		
		

		System.out.println("test data2:"+data);
		
		return data;
	}
	
	/*
	 * String -> bezigheid
	 * Long -> productiviteit
	 */
	public Map<String, Long> statQuestions(List<String> UserIDs, boolean all, Date Start, Date Stop, List<Integer> questionIDs
			, StatisticsDateType statdtype, String courseID)
	{
		currentUser = userManager.getCurrentUser();
		List<String> l = createDateStringKeys(Start, Stop, statdtype);
		Map<String, Long> data = new LinkedHashMap<String, Long>();
		for (int i = 0; i < l.size(); i++){
			data.put(l.get(i), 0L);
		}
		Map<String, Long> data_amt = new HashMap<String, Long>();
		List<Entity> userlist = convertUserList(UserIDs, all);
		for (int i = 0; i < userlist.size(); i++){
			Entity user = userlist.get(i);
			List<Activity> activities = activityManager.getActivitiesFiltered(user.getKey(), Start, Stop);
			for (int j = 0; j < activities.size(); j++){
				Activity act = activities.get(j);
				List<Question> listq = act.getQuestionnaire();
				
				// if courseID is not equal to "" then we must check if the course of the activity
				// corresponds to the given courseID course
				boolean coursecorrespondsORnocourseid = false;
				boolean courseisinuserscourselist = false;
				if (courseID.equals("")){
					coursecorrespondsORnocourseid = true;
					courseisinuserscourselist = true;
				}else{
					if (act instanceof getCourseable){
						Course crs = ((getCourseable)act).getCourse();
						
						if (crs == courseManager.getCourseByID(courseID)){
							coursecorrespondsORnocourseid = true;
						}
						if (currentUser.getAllCourseIDs().contains(crs.getCourseID())){
							courseisinuserscourselist = true;
						}
					}
				}
				
				if (act.getStopDate() != null
						&& listq != null
						&& (act.getAType() == ActivityType.LESSON || act.getAType() == ActivityType.STUDY)
						&& coursecorrespondsORnocourseid
						&& courseisinuserscourselist){
					// 1- activiteit niet af
					// 2- vragen niet beantwoord
					// 3- moet van type les of study zijn
					// 4- vak is hetzelfde als meegegeven id of leeg
					for (int k = 0; k < listq.size(); k++){
						Question q = listq.get(k);
						if (questionIDs.contains(q.getQuestionID())){
							long begrip = 0;
							if (q.getAnswer() != null && !q.getAnswer().equals("")) // niet beantwoord
							{
								try{
									begrip = Integer.parseInt(q.getAnswer());
								}
								catch(NumberFormatException e){
									System.out.println(e);
								}
								String datatype = getDateStatType(act.getStartDate(), statdtype);
								if (data.containsKey(datatype)){
									data.put(datatype, data.get(datatype)+begrip);
									if (data_amt.containsKey(datatype)){
										data_amt.put(datatype, data_amt.get(datatype)+1);
									}else{
										data_amt.put(datatype, 1L);
									}
								}else{
								}
							}
						}
					}
				}
			}
		}
		
		
		
		for (String s : data.keySet()){
			if (data_amt.get(s) != null){
				data.put(s, data.get(s)/data_amt.get(s));
			}
		}
		
		System.out.println("test data:"+data);
		
		return data;
	}
}
